# -*- coding: utf-8 -*-
# @Author   : SongLiangCheng
# @QQ       : 2192383945
# @Time     : 2022/12/2 15:00
# @File     : blog.py 
# @Project  : scraping
# @Desc     : this is a toy
import dataclasses
import logging
import re
from concurrent.futures._base import Future
from .utils import replace_str
from dataclasses import dataclass
from pathlib import Path
from urllib.parse import urlparse

import requests
from pyquery import PyQuery as pq, PyQuery

from .config import Configuration
from .http import get_page

logger = logging.getLogger(__name__)

@dataclasses.dataclass(order=True)
class urlObj:
    basename: str
    dirname: str
    path: Path
    fullpath: str
@dataclass
class Blog:
    config: Configuration

    def run(self, URL):
        get_page(URL, get_doc=self.get_doc, parse_content=self.parse_content, parse_next_url=self.parse_next_url,
                 save_contents=self.save_contents, works=self.config.works)

    def parse_content(self,doc:dict|PyQuery):
        raise Exception('不实现')

    def parse_next_url(self,doc:PyQuery|str):
        raise Exception('不实现')

    def get_doc(self, url: str) -> [None,None]:
        raise Exception('不实现')

    def process_path(self, path: str) -> str:
        return re.sub('\?.*', '', path)



    def geturl(self, url: str) -> urlObj | None:

        if url.startswith('//'):
            url = f'https:{url}'
        if url.startswith('/'):
            url = f'{self.config.base_domain}{url.lstrip("/")}'

        path = urlparse(url).path
        basename = Path(path).name
        dirname = str(Path(path).parent).lstrip('/').lstrip('\\')
        path = Path(self.config.basepath, dirname)
        fullpath = self.process_path(str(path / basename))
        return urlObj(basename=basename, dirname=dirname, path=path, fullpath=fullpath)

    def write_content(self, url: str, is_img=False) -> None:
        urlobj = self.geturl(url)
        logger.debug(f'write_content 获取到的urlobj {urlobj}')
        if Path(urlobj.fullpath).exists():
            logger.debug(f'{url}对应的路径{urlobj.fullpath}已经存在，所以直接跳过解析')
            return

        if not urlobj.path.exists():
            try:
                urlobj.path.mkdir(parents=True)
            except:
                pass
        if is_img:
            if not Path(urlobj.fullpath).exists():
                with open(urlobj.fullpath, 'wb') as fb:
                    fb.write(requests.get(url).content)
            return
        doc = pq(url)
        # image save
        if (doc('img')):
            doc = self.image_save(doc)
        # image save
        if (doc('script')):
            self.script_save(doc)
        if (doc('link')):
            # css save
            self.css_save(doc)
        if not Path(urlobj.fullpath).exists():
            with open(urlobj.fullpath, 'w', encoding='utf8') as fb:
                fb.write(doc.html())

    def css_save(self, doc: PyQuery):
        links = doc('link').items()
        for link in links:
            url = link.attr('href')
            try:
                if url is None:
                    raise Exception(f'{link}的URL是空的')
                self.write_content(url)
            except ValueError as e:
                logger.warning(e)
                continue

    def script_save(self, doc: PyQuery):
        scripts = doc('script').items()
        for script in scripts:
            url = script.attr('src')
            try:
                if url is None:
                    raise Exception(f'{script}的URL是空的')
                self.write_content(url, is_img=True)
            except Exception as e:
                logger.warning(e)
                continue

    def image_save(self, doc: PyQuery) -> PyQuery:
        images = doc('img').items()
        for image in images:

            try:
                imgurl = image.attr('src')
                if imgurl is None:
                    raise Exception(f'{image}的URL是空的')
                # https://img2022.cnblogs.com/blog/1204490/202211/1204490-20221123103411299-1463539510.png
                self.write_content(imgurl, is_img=True)
            except Exception as e:
                logger.warning(e)
                continue

            if imgurl.startswith('http'):
                image.attr('src', re.sub('http(s)?://[^/]+', '', imgurl))
        return doc

    def save_contents(self, daemons):
        daemons: list[Future]
        results = []
        for daemon in daemons:
            results.append(daemon.result())
            # daemons[0].result()[0]

        if not Path(self.config.basepath).exists():
            try:
                Path(self.config.basepath).mkdir(parents=True)
            except:
                pass
        with open((indexfile := self.config.basepath / self.config.indexfile), 'w', encoding='utf8') as fb:
            for result in results:
                for line in result:
                    fb.write(line)
        # 文件前后添加
        # indexfile
        self.add_html()
        # 替换域名
        # base_domain -> your domain
        fileDir = self.config.basedir

        if not self.config.only_outline:
            # replace_str(文件夹路径，替换前的字符串，替换后的字符串)
            replace_str(fileDir, self.config.base_domain, self.config.public_domain)

    def add_html(self):
        with open((indexfile := self.config.basepath / self.config.indexfile), 'r', encoding='utf8') as fb:
            contents = fb.readlines()

            contents.insert(0, """
        <!doctype html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport"
                  content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
            <meta http-equiv="X-UA-Compatible" content="ie=edge">
            <title>Document</title>
            <style>
                .main {
                    display: flex;
                    flex-direction: column-reverse;
                    color: #4c4444;
                    font-size: 17px;
                    padding-left: 75px;
                    padding-right: 55px;
                }
            </style>
        </head>
        <body>
        <div class="main">
                    """)
            contents.append("""
        </div>
        </body>
        </html>
                    """)

        with open((indexfile := self.config.basepath / self.config.indexfile), 'w', encoding='utf8') as fb:
            fb.write("".join(contents))

